﻿using System;
using MoroMoro.Samples.ToDoList.Base.Domain.Builders;

namespace MoroMoro.Samples.ToDoList.Domain.ToDos
{
    partial class Memo
    {
        /// <summary>
        /// <see cref="Memo">メモ</see>のビルダです。
        /// </summary>
        [Serializable]
        public sealed class Builder : EntityBuilder<Memo, IBuildErrorHandler>
        {
            /// <summary>
            /// <see cref="Memo.Text">メモのテキスト</see>の文字数の最大値を取得します。
            /// </summary>
            public static readonly int TextMaxLength = 1000;


            /// <summary>
            /// <see cref="Memo">メモ</see>の作成を目的として、<see cref="Builder"/> クラスの新しいインスタンスを初期化します。
            /// </summary>
            internal Builder()
                : base()
            {
            }

            /// <summary>
            /// <see cref="Memo">メモ</see>の編集を目的として、<see cref="Builder"/> クラスの新しいインスタンスを初期化します。
            /// </summary>
            /// <param name="target">編集対象の<see cref="Memo">メモ</see>。</param>
            /// <exception cref="System.ArgumentNullException">target が null です。</exception>
            internal Builder(Memo target)
                : base(target)
            {
                Text = Target.Text;
            }


            /// <summary>
            /// <see cref="Memo.Text">メモのテキスト</see>に指定する値を取得または設定します。
            /// </summary>
            public string Text
            {
                get;
                set;
            }


            /// <summary>
            /// ビルダの現在のエラーを通知します。エラーが無い場合はハンドラには何も通知されません。
            /// </summary>
            /// <param name="handler">エラーハンドラ。</param>
            /// <exception cref="System.ArgumentNullException">handler が null です。</exception>
            public override void NotifyErrorTo(IBuildErrorHandler handler)
            {
                if (handler == null)
                {
                    throw new ArgumentNullException("handler");
                }

                NotifyTextErrorTo(handler);
            }

            /// <summary>
            /// <see cref="Memo.Text">メモのテキスト</see>に関するエラーを通知します。エラーが無い場合はハンドラには何も通知されません。
            /// </summary>
            /// <param name="handler">エラーハンドラ。</param>
            /// <exception cref="System.ArgumentNullException">handler が null です。</exception>
            public void NotifyTextErrorTo(ITextErrorHandler handler)
            {
                if (handler == null)
                {
                    throw new ArgumentNullException("handler");
                }

                if ((Text != null) && (TextMaxLength < Text.Length))
                {
                    handler.HandleTextTooLongError();
                }
            }


            /// <summary>
            /// <see cref="Memo">メモ</see>をビルドします。
            /// </summary>
            /// <returns>ビルドされた<see cref="Memo">メモ</see>。</returns>
            /// <exception cref="System.InvalidOperationException"><see cref="Memo">メモ</see>をビルドできる状態ではありません。</exception>
            public override Memo Build()
            {
                if (!IsValid)
                {
                    throw new InvalidOperationException();
                }

                var result = IsForCreation ? new Memo() : Target;
                result.Text = Text ?? string.Empty;
                return result;
            }
        }
    }
}
